// vue.config.js
const path = require("path");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const VConsolePlugin = require("vconsole-webpack-plugin");
const CompressionPlugin = require("compression-webpack-plugin"); // 引入gzip压缩插件
const webpack = require("webpack");
const AddAssetHtmlPlugin = require("add-asset-html-webpack-plugin");
const dll = require("./config.dll.js");
const IS_PROD = process.env.NODE_ENV === "production";
const timeStamp = new Date().getTime();
const HappyPack = require("happypack");
const Os = require("os");

const TARGET_URL = "http://127.0.0.1:8000/";

function resolve(dir) {
  return path.join(__dirname, dir);
}
module.exports = {
  publicPath: IS_PROD ? "./" : "/",

  // 将构建好的文件输出到哪里
  outputDir: "dist/static",

  // 指定生成的 index.html 的输出路径
  indexPath: "index.html",

  // 是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了，但是这会让你的应用额外增加 10kb 左右。
  runtimeCompiler: false,

  // 默认情况下 babel-loader 会忽略所有 node_modules 中的文件。如果你想要通过 Babel 显式转译一个依赖，可以在这个选项中列出来。
  transpileDependencies: [],

  // 生产环境关闭 source map
  productionSourceMap: true,

  lintOnSave: true,

  // 配置css
  css: {
    // 是否使用css分离插件 ExtractTextPlugin
    extract: IS_PROD,
    sourceMap: false,
    requireModuleExtension: true,
    // css预设器配置项
    loaderOptions: {
      postcss: {
        plugins: [
          require("postcss-px2rem")({
            remUnit: 100
          })
        ]
      },
      sass: {
        prependData: `
          @import "@/assets/css/_layout.scss";
        `
      }
    }
    // 启用 CSS modules for all css / pre-processor files.
    // modules: false
  },

  // 是一个函数，会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。
  chainWebpack: config => {
    // 配置别名
    config.resolve.alias
      .set("@", resolve("src"))
      .set("assets", resolve("src/assets"))
      .set("components", resolve("src/components"))
      .set("views", resolve("src/views"));

    config.optimization.minimizer("terser").tap(args => {
      // 去除生产环境console
      args[0].terserOptions.compress["drop_console"] = true;
      return args;
    });

    // 修复HMR
    config.resolve.symlinks(true);
    // 压缩代码
    // config.optimization.minimize(true);
    // 分割代码
    config.optimization.splitChunks({
      chunks: "all"
    });
    config.plugins.delete("named-chunks");
  },

  configureWebpack: config => {
    if (IS_PROD) {
      config.plugins.push(
        new BundleAnalyzerPlugin({
          analyzerMode: "disabled" // 打包后是否自动显示分析情况
        })
      );
      config.plugins.push(
        new CompressionPlugin({
          // gzip压缩配置
          test: /\.js$|\.html$|\.css/, // 匹配文件名
          threshold: 102400, // 对超过10kb的数据进行压缩
          deleteOriginalAssets: false // 是否删除原文件
        })
      );
    }

    config.plugins.push(
      new VConsolePlugin({
        enable: false // 测试显示 生产环境不显示vConsole
      })
    );

    config.plugins.push(
      ...Object.keys(dll).map(name => {
        return new webpack.DllReferencePlugin({
          manifest: require(`./public/vendor/${name}-manifest.json`)
        });
      }),
      // 将 dll 注入到 生成的 html 模板中
      new AddAssetHtmlPlugin({
        // dll文件位置
        filepath: path.resolve(__dirname, "./public/vendor/*.js"),
        // dll 引用路径
        publicPath: "./vendor",
        // dll最终输出的目录
        outputPath: "./vendor"
      }),
      // 开启多线程构建
      new HappyPack({
        loaders: ["babel-loader", "vue-loader", "url-loader", "sass-loader"],
        cache: true,
        threads: Os.cpus().length
      })
    );

    const hashValue =
      process.env.NODE_ENV === "development" ? "[hash:8]" : "[contenthash:8]";
    config.output = {
      ...config.output,
      filename: `static/js/[name].${hashValue}.${timeStamp}.js`,
      chunkFilename: `static/js/[name].${hashValue}.${timeStamp}.js`
    };
    return {
      module: {
        rules: [
          {
            test: require.resolve("snapsvg/dist/snap.svg.js"),
            use: "imports-loader?this=>window,fix=>module.exports=0"
          }
        ]
      },
      resolve: {
        alias: {
          snapsvg: "snapsvg/dist/snap.svg.js"
        }
      }
    };
  },

  devServer: {
    host: "0.0.0.0",
    port: 8090, // 端口号
    https: false, // https:{type:Boolean}
    open: false, // 配置自动启动浏览器  open: 'Google Chrome'-默认启动谷歌
    // disableHostCheck: true, // webpack4.0 开启热更新

    // 配置多个代理
    proxy: {
      "/python": {
        target: TARGET_URL,
        changeOrigin: true,
        pathRewrite: {
          "^/python": "/python"
        }
      }
    },
    before(app, server) {
      app.get(/.*.(js) | .*.*.(js)$/, (req, res, next) => {
        req.url = req.url + ".gz";
        res.set("Content-Encoding", "gzip");
        next();
      });
    }
  }
};
